package com.hz.cheetah.server;

import com.hz.cheetah.common.bean.RpcRequest;
import com.hz.cheetah.common.bean.RpcResponse;
import com.hz.cheetah.common.util.StringUtil;
import com.hz.cheetah.server.imp.RpcSession;
import net.sf.cglib.reflect.FastClass;
import net.sf.cglib.reflect.FastMethod;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

/**
 * Created by yangchuan on 16/7/7.
 */
public class RpcServiceRunTask implements Runnable {

    private static Logger logger = LoggerFactory.getLogger(RpcServiceRunTask.class);
    RpcRequest request;
    Object serviceBean;
    RpcSession session;

    public RpcServiceRunTask(RpcSession session,Object target,RpcRequest request) {
            this.request = request;
            this.serviceBean = target;
            this.session = session;
    }


    /**
     * When an object implementing interface <code>Runnable</code> is used
     * to create a thread, starting the thread causes the object's
     * <code>run</code> method to be called in that separately executing
     * thread.
     * <p>
     * The general contract of the method <code>run</code> is that it may
     * take any action whatsoever.
     *
     * @see Thread#run()
     */
    @Override
    public void run() {
        RpcResponse response = new RpcResponse();
        response.setRequestId(request.getRequestId());
        try {
            Object object = handle();
            response.setResult(object);
            object = null;
        } catch (Exception e) {
            response.setException(e);
            logger.error("handle result failure", e);
        }
        session.write(response);
        response = null;
    }

    private Object handle() throws Exception {
        // 获取服务对象


        // 获取反射调用所需的参数
        Class<?> serviceClass = serviceBean.getClass();
        String methodName = request.getMethodName();
        Class<?>[] parameterTypes = request.getParameterTypes();
        Object[] parameters = request.getParameters();
        // 使用 CGLib 执行反射调用
        FastClass serviceFastClass = FastClass.create(serviceClass);
        FastMethod serviceFastMethod = serviceFastClass.getMethod(methodName, parameterTypes);
        return serviceFastMethod.invoke(serviceBean, parameters);
    }
}
